﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using tools_library;
using System.Runtime.InteropServices;
using System.Net;

namespace rserver
{
    public partial class frmMain : Form
    {
        private HelperTool Helper = new HelperTool();
        //private bool IsControlled=false;
        private NetworkTool Service;
        private NetworkTool.MessageReceivedDelegate MessageReceived;
        private int LocalPort = 2020;

        private enum SizeConstants: int {
            HORZRES = 8, 
            VERTRES = 10,
            SRCCOPY = 0xCC0020,
            SRCINVERT = 0x660046,
            USE_SCREEN_WIDTH = -1,
            USE_SCREEN_HEIGHT = -1
        }

        private Bitmap CaptureCursor(ref int x, ref int y)
        {
            Bitmap bmp;
            IntPtr hicon;
            WindowsApi.CURSORINFO ci = new WindowsApi.CURSORINFO();
            WindowsApi.ICONINFO icInfo;
            ci.cbSize = Marshal.SizeOf(ci);
            if (WindowsApi.GetCursorInfo(out ci))
            {
                if (ci.flags == WindowsApi.CURSOR_SHOWING)
                {
                    hicon = WindowsApi.CopyIcon(ci.hCursor);
                    if (WindowsApi.GetIconInfo(hicon, out icInfo))
                    {
                        x = ci.ptScreenPos.x - ((int)icInfo.xHotspot);
                        y = ci.ptScreenPos.y - ((int)icInfo.yHotspot);
                        Icon ic = Icon.FromHandle(hicon);
                        bmp = ic.ToBitmap();

                        return bmp;
                    }
                }
            }
            return null;
        }

        private Bitmap CaptureScreen()
        {
            //CAPTURE THE BITMAP
            // Size size is how big an area to capture
            // pointOrigin is the upper left corner of the area to capture
            int width = Screen.PrimaryScreen.Bounds.X + Screen.PrimaryScreen.Bounds.Width;
            int height = Screen.PrimaryScreen.Bounds.Y + Screen.PrimaryScreen.Bounds.Height;
            Size size = new Size(width, height);
            Point pointOfOrigin = new Point(0, 0);
            Bitmap desktopBitmap = new Bitmap(size.Width, size.Height);
            using (Graphics graphics = Graphics.FromImage(desktopBitmap))
            {
                graphics.CopyFromScreen(pointOfOrigin, new Point(0, 0), size);
            }
            //CAPTURE CURSOR
            int cursorX=0, cursorY=0;
            Bitmap cursorBitmap = CaptureCursor(ref cursorX,ref cursorY);
            //MERGE THE CURSOR INTO DESKTOP BITMAP
            if (cursorBitmap != null)
            {
                Graphics g;
                Rectangle r;
                r = new Rectangle(cursorX, cursorY, cursorBitmap.Width, cursorBitmap.Height);
                g = Graphics.FromImage(desktopBitmap);
                g.DrawImage(cursorBitmap, r);
                g.Flush();
                return desktopBitmap;
            }
            else
            {
                return desktopBitmap;
            }
        }

        private Bitmap GrabScreen()
        {
            return GrabScreen(0, 0, (int)SizeConstants.USE_SCREEN_WIDTH, (int)SizeConstants.USE_SCREEN_HEIGHT);
        }

        private Bitmap GrabScreen(int x,int y, int width, int height)
        {
            try
            {
                IntPtr hdesktopDC, hoffScreenDC, hBitmap, hOldBitmap;
                Bitmap myBitmap = null;
                hOldBitmap = IntPtr.Zero;

                hdesktopDC = WindowsApi.CreateDC("DISPLAY", "", "", IntPtr.Zero);
                if (hdesktopDC != null)
                {
                    if (width == (int)SizeConstants.USE_SCREEN_WIDTH)
                    {
                        width = WindowsApi.GetDeviceCaps(hdesktopDC, (int)SizeConstants.HORZRES);
                    }
                    if (height == (int)SizeConstants.USE_SCREEN_HEIGHT)
                    {
                        height = WindowsApi.GetDeviceCaps(hdesktopDC, (int)SizeConstants.VERTRES);
                    }
                    hoffScreenDC = WindowsApi.CreateCompatibleDC(hdesktopDC);
                    if (hoffScreenDC != null)
                    {
                        hBitmap = WindowsApi.CreateCompatibleBitmap(hdesktopDC, width, height);
                        if (hBitmap != null)
                        {
                            //copy the image and create instance of the bitmap class
                            hOldBitmap = WindowsApi.SelectObject(hoffScreenDC, hBitmap);
                            WindowsApi.BitBlt(hoffScreenDC, 0, 0, width, height, hdesktopDC, x, y, WindowsApi.TernaryRasterOperations.SRCCOPY);
                            myBitmap = Bitmap.FromHbitmap(hBitmap);
                            //clean up
                        }
                        WindowsApi.DeleteObject(WindowsApi.SelectObject(hoffScreenDC, hOldBitmap));
                    }
                    WindowsApi.DeleteObject(WindowsApi.SelectObject(hdesktopDC, hOldBitmap));
                }
                return myBitmap;
            }
            catch 
            {
                return null;
            }
        }

        private void OnMessageReceived(object sender, MessageReceivedArgs e)
        {
            try
            {
                switch (e.Command)
                {
                    case "$leftclick":
                        WindowsApi.mouse_event((uint)WindowsApi.MouseEventFlags.LEFTDOWN, 0, 0, 0, UIntPtr.Zero);
                        WindowsApi.mouse_event((uint)WindowsApi.MouseEventFlags.LEFTUP, 0, 0, 0, UIntPtr.Zero);
                        break;
                    case "$rightclick":
                        WindowsApi.mouse_event((uint)WindowsApi.MouseEventFlags.LEFTDOWN, 0, 0, 0, UIntPtr.Zero);
                        WindowsApi.mouse_event((uint)WindowsApi.MouseEventFlags.LEFTUP, 0, 0, 0, UIntPtr.Zero);
                        break;
                    case "$startview":
                        if (!e.RemoteNode.Attributes.Contains("view_flag"))
                        {
                            e.RemoteNode.Attributes.Add("view_flag", "");
                        }
                        break;
                    case "$startcontrol":
                        //IsControlled = true;
                        if (!e.RemoteNode.Attributes.Contains("control_flag"))
                        {
                            e.RemoteNode.Attributes.Add("control_flag", "");
                        }
                        break;
                    case "$stopcontrol":
                        //IsControlled = false;
                        if (e.RemoteNode.Attributes.Contains("control_flag"))
                        {
                            e.RemoteNode.Attributes.Remove("control_flag");
                        }
                        if (e.RemoteNode.Attributes.Contains("view_flag"))
                        {
                            e.RemoteNode.Attributes.Remove("view_flag");
                        }
                        break;
                    case "$screencap":
                        GrabScreen();
                        break;
                    case "$mousepos": //190*344
                        string[] data = e.Body.Split((new string[] {"*"}).ToString().ToCharArray());
                        int x, y;
                        int.TryParse(data[0],out x);
                        int.TryParse(data[1], out y);

                        Point newpos = new Point(x, y);
                        Cursor.Position = newpos;
                        break;
                    case "$message":
                        break;
                    case "$file":
                        break;
                    case "$showmsg":
                        MessageBox.Show(e.Body,"Message from Administrator",MessageBoxButtons.OK);
                        break;
                }
            }
            catch
            {
            }
        }

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            System.Drawing.Bitmap bmp = (imageList1.Images["NormalIcon"] as Bitmap);
            this.notifyIcon1.Icon = Icon.FromHandle(bmp.GetHicon());
            //Dns.GetHostByName("");
            //
            Service = new NetworkTool();
            MessageReceived = new NetworkTool.MessageReceivedDelegate(OnMessageReceived);
            //
            IPAddress[] addresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            IPAddress localip;
            if (addresses[0].ToString() == "127.0.0.1" && addresses.Length > 1)
            {
                localip = addresses[1];
            }
            else
            {
                localip = addresses[0];
            }
            this.Text += " " + localip.ToString() + ":" + this.LocalPort.ToString();
            //start the server
            Service.StartServer(this.LocalPort, MessageReceived, (ISynchronizeInvoke)this);
            tmrScreenControl.Start();
            lvwConnections.Left = 0;
            lvwConnections.Top = 0;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
            this.BringToFront();
            //this.Show();
            //this.Focus();
        }

        private void frmMain_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Visible = false;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Helper.SaveSetting("FrameSize", "10");
            //Helper.SaveSetting("ServerName", "temp");
            //Helper.ShowConfigDialog();
            //Helper.WriteLog("some log");
            //IntPtr hBitmap = GrabScreen().GetHbitmap();
            //pictureBox1.Image = Image.FromHbitmap(hBitmap);
        }

        private void tmrScreenControl_Tick(object sender, EventArgs e)
        {
            Bitmap grabbed = CaptureScreen(); //GrabScreen();
            byte[] bytes = Helper.BitmapToByte(grabbed);
            string data = Convert.ToBase64String(bytes);
            Node client = null;
            foreach (object obj in Service.Connections.Values)
            {
                client = obj as Node;
                if (client.Attributes.Contains("control_flag") ||
                    client.Attributes.Contains("view_flag"))
                {
                    Service.SendMessage(client, "$screen", data);
                    if (!lvwConnections.Items.ContainsKey(client.ToString()))
                    {
                        ListViewItem item = new ListViewItem(client.ToString());
                        item.Name = client.ToString();
                        lvwConnections.Items.Add(item);
                    }
                }
                else if (client.Attributes.Contains("file_transfer_flag"))
                {
                    //add functionality here
                    if (!lvwConnections.Items.ContainsKey(client.ToString()))
                    {
                        ListViewItem item = new ListViewItem(client.ToString());
                        item.Name = client.ToString();
                        lvwConnections.Items.Add(item);
                    }
                }
                else
                {
                    if (lvwConnections.Items.ContainsKey(client.ToString()))
                    {
                        lvwConnections.Items.RemoveByKey(client.ToString());
                    }
                }
                //break;
            }
        }

        private void frmMain_Resize(object sender, EventArgs e)
        {
            lvwConnections.Size = this.ClientRectangle.Size;
        }
    }
}
